Spring Database Initialization
January 4, 2022 • ☕️ 4 min read
This article will give you examples of how to use Data Definition Language(DDL) and Data Manipulation Language(DML) files and differences
Here is the official Spring Doc about it : https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#howto.data-initialization.using-jpa
If you search with “Spring Database Initialization” it mostly forward us to older Spring releases
I like yml format than .properties which is equal actually
I will refer this below application.yml in this blog post mostly.
#
is for comments
spring:
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
show-sql: true
defer-datasource-initialization: true
#database: h2 #same as database-platform, it doesn't effect schema-{platform}.sql and data-{platform}.sql names
#database-platform: org.hibernate.dialect.H2Dialect
datasource:
url: jdbc:h2:mem:testdb #ALWAYS, EMBEDDED or NEVER will be calculated from h2
username: h2-user
password: h2-pass
driverClassName: org.h2.Driver
#initialization-mode: always # deprecated, moved to under sql.init, DON'T USE
#platform: h2 #deprecated, moved to under sql.init, , DON'T USE
sql:
init:
#continue-on-error: true
mode: ALWAYS
platform: h2 #it effect schema-{platform}.sql and data-{platform}.sql names
h2:
console:
enabled: true
path: /h2
logging:
level:
#root: INFO
#org.hibernate.SQL: TRACE
#spring.sql: TRACE
#javax.sql: TRACE
#org.h2.jdbc: TRACE
org.springframework.jdbc: TRACE
debug: false
In Spring Boot 2.5. spring.datasource.* properties related to DataSource initialization have been deprecated and migrated to new spring.sql.init.* properties. https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes#sql-script-datasource-initialization spring.datasource is being mapped to DataSourceProperties beans automaticially and some fieds are deprecated in Java and yml sides.
You can use below code to see the Spring bean by below code
@Autowired
JpaProperties jpaProperties;
@Autowired
HibernateProperties hibernateProperties;
@Autowired
DataSourceProperties dataSourceProperties;
@Autowired
SqlInitializationProperties sqlInitializationProperties;
@PersistenceContext
EntityManager em;
@Autowired
EntityManagerFactory entityManagerFactory;
You can check it out what fields deprecated from https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.html Some of them
- spring.datasource.initialization-mode ==> spring.sql.init.mode
- spring.datasource.platform ==> spring.sql.init.platform
There are 3 types of database schema creating(DDL) and importing data(DML): Hibernate and JDBC SQL scripts and high level tools like Flywaydb or Liquibase. We will talk about Hibernate and JDBC SQL scripts methods here.
SQL scripts method means that schema.sql is for schema and data.sql is for putting data.
- spring.jpa.hibernate.ddl-auto default value is create-drop if it is embedded by looking at JDBC url spring.datasource.url
- import.sql is executed by Hibernate if hibernate.ddl-auto is create or create-drop
- if sql.init.mode is embedded it execute import.sql
- creation schema from Jpa entities is managed by generate-ddl is true or hibernate.ddl-auto
The below table indicate that when schema.sql,data.sql, import.sql and schema from entities are working. initialization-mode, generate-ddl and hibernate.ddl-auto are inputs
initialization-mode |
generate-ddl |
hibernate.ddl-auto |
schema.sql | data.sql | create schema from entities | import.sql |
---|---|---|---|---|---|---|
never | true | create | false | false | true | true |
never | true | none | false | false | true | false |
never | false | create | false | false | true | true |
never | false | none | false | false | false | false |
While multiple data source initialization technologies is not recommendded you can still use JDBC init and hibernate together.
spring.jpa.defer-datasource-initialization defer schema.sql and data.sql after hibernate schema
- When defer-datasource-initialization: false
-
- schema.sql-> data.sql->
JPA schema create from Entities
-> import.sql
- schema.sql-> data.sql->
- When defer-datasource-initialization: true
-
JPA schema create from Entities
-> import.sql -> schema.sql-> data.sql
sql.init.platform manage the name of data-{platform}.sql and schema-{platform}.sql with some bugs. Default is all and it means schema.sql and data.sql
Spring Boot chooses a default value for you based on whether it thinks your database is embedded. It defaults to create-drop if no schema manager has been detected or none in all other cases. An embedded database is detected by looking at the Connection type and JDBC url. hsqldb, h2, and derby are candidates, and others are not.
Sometimes calculating default values are incorrect for DDL and DML. So I am planning to move all those to Flyway.